package cn.com.jdyun.service.impl;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import cn.com.jdyun.mapper.ext.ExtSysConfigMapper;
import cn.com.jdyun.pojo.SysConfig;
import cn.com.jdyun.util.MD5Util;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.Page;
import com.sun.mail.util.MailSSLSocketFactory;

import cn.com.jdyun.config.EmailConfig;
import cn.com.jdyun.config.TelConfig;
import cn.com.jdyun.dto.UserCredit;
import cn.com.jdyun.exception.BdexGatewayException;
import cn.com.jdyun.exception.WarningException;
import cn.com.jdyun.mapper.ext.ExtUserMapper;
import cn.com.jdyun.pojo.User;
import cn.com.jdyun.pojo.UserSec;
import cn.com.jdyun.service.RefereeService;
import cn.com.jdyun.service.UserSecService;
import cn.com.jdyun.service.UserService;
import cn.com.jdyun.service.UserWalletService;
import cn.com.jdyun.util.Constant;
import cn.com.jdyun.util.RedisUtil;
import cn.com.jdyun.util.WebConstants;


@Service
public class UserServiceImpl implements UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    @Autowired
    private ExtUserMapper userMapper;

    @Autowired
    private RefereeService refereeService;

    @Autowired
    private ExtSysConfigMapper sysConfigMapper;

    @Autowired
    TelConfig telConfig;

    @Autowired
    EmailConfig emailConfig;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    private UserWalletService userWalletService;
    
    @Autowired
    private UserSecService userSecService;

    @Transactional(readOnly = true)
    @Override
    public User getById(String id) {
        return userMapper.selectByPrimaryKey(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUserFlag(String userId, Byte flag) throws BdexGatewayException {
        int result = userMapper.updateUserFlag(userId, flag);
        if (result <= 0) {
            throw new BdexGatewayException("锁定用户失败!");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(User user) throws BdexGatewayException {
        // 生成用户8位唯一id
        String lastId = userMapper.selectLastId();
        if (StringUtils.isBlank(lastId)) {
            lastId = "0";
        }
        Long id = Long.valueOf(lastId) + 1;
        if(id < 10000000) {
        	id += 10000000;
        }
        user.setId(String.format("%08d", id));

        Date cur = new Date();

        user.setCode(createCode());
        if (user.getFlag() == null) {
            user.setFlag(Byte.valueOf("0"));
        }
        if (user.getAdmin() == null) {
            user.setAdmin(false);
        }
        user.setCreateTime(cur);
        user.setUpdateTime(cur);
        if (StringUtils.isNotBlank(user.getPassword())) {
            user.setPassword(MD5Util.encode(user.getPassword()));
        }
        user.setTexLevel(0);
        userMapper.insert(user);

        if (user.getNickName() != null) {
            redisUtil.hset(User.class.getName() + ".nickName", user.getId(), user.getNickName());
        }
    }
    private String createCode(){
        // 设置推荐码
        String refereeCode = Constant.generateReffereeCode();
        String str = userMapper.inqueryRefereeCode(refereeCode);
        while(str != null){
            createCode();
        }
        return refereeCode;
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void regist(User user) throws BdexGatewayException {
        // 保存用戶信息
        save(user);
        // 为用户创建钱包
        for (String coinType : Constant.COINRRAY) {
            userWalletService.createWallet(user.getId(), coinType, "0");
        }
        // 奖励用户1000糖果
        SysConfig config = sysConfigMapper.selectByCode(Constant.REGEST_CANDY);
        userWalletService.presentCoin(user.getId(), config.getInitValue(), Constant.CANDY, false);
        // 保存用户和推荐人关系
        refereeService.add(user.getId(), user.getReferee());
        if (StringUtils.isNotBlank(user.getReferee())) {
            // 推荐人赠送100糖果
            SysConfig regestCandyConfig = sysConfigMapper.selectByCode(Constant.INVITE_CANDY);
            userWalletService.presentCoin(user.getReferee(), regestCandyConfig.getInitValue(), Constant.CANDY, true);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrUpdate(User user) throws BdexGatewayException {

        if (StringUtils.isBlank(user.getId())) {
            save(user);
        } else {
            Date cur = new Date();
            user.setUpdateTime(cur);
            if (StringUtils.isNotBlank(user.getPassword())) {
                user.setPassword(user.getPassword());
            }
            userMapper.updateByPrimaryKeySelective(user);
        }

        if (user.getNickName() != null) {
            redisUtil.hset(User.class.getName() + ".nickName", user.getId(), user.getNickName());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUserPwdEmail(User user) throws BdexGatewayException {
        Date cur = new Date();
        user.setUpdateTime(cur);
        if (StringUtils.isNotBlank(user.getPassword())) {
            user.setPassword(user.getPassword());
        }
        String email = user.getEmail();
        String password = user.getPassword();
        int result = userMapper.updateUserPwdEmail(email, password);
        if (result <= 0) {
            throw new BdexGatewayException("密码业务操作失败!");
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUserPwdPhone(User user) throws BdexGatewayException {
        Date cur = new Date();
        user.setUpdateTime(cur);
        if (StringUtils.isNotBlank(user.getPassword())) {
            user.setPassword(MD5Util.encode(user.getPassword()));
        }
        String phone = user.getPhone();
        String password = user.getPassword();
        int result1 = userMapper.updateUserPwdPhone(phone, password);
        if (result1 <= 0) {
            throw new BdexGatewayException("更新密码失败!");
        }
        String manageId = userMapper.findManageId(user);
        if(StringUtils.isNotEmpty(manageId)){
            int result2 = userMapper.updateManagePwdPhone(phone, password);
            if (result2 <= 0) {
                throw new BdexGatewayException("更新密码失败!");
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteById(String id) throws BdexGatewayException {
        if (deleteEnable(id)) {
            userMapper.deleteByPrimaryKey(id);
        }
    }

    @Transactional(readOnly = true)
    @Override
    public boolean deleteEnable(String id) throws BdexGatewayException {
        return false;
    }

    @Transactional(readOnly = true)
    @Override
    public List<User> selectAll() throws BdexGatewayException {
        return userMapper.selectBySelective(null);
    }

    @Transactional(readOnly = true)
    @Override
    public List<User> selectBySelective(User user) {
        if (StringUtils.isNotBlank(user.getPassword())) {
            user.setPassword(MD5Util.encode(user.getPassword()));
        }
        return userMapper.selectBySelective(user);
    }

    @Override
    public String inqueryUserId(String phone) {
        return userMapper.inqueryUserId(phone);
    }

    @Transactional(readOnly = true)
    @Override
    public Page<User> pageData(Map<String, Object> condition) throws BdexGatewayException {
        return userMapper.pageData(condition);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserCredit login(String username, String password) throws BdexGatewayException {
        password  = MD5Util.encode(password);
        UserCredit user = userMapper.login(username, password);
        if(user != null && user.getFlag() == 1) {
        	UserSec us = userSecService.queryByUserId(user.getId());
        	if(us == null) {
        		user.setSecFlag(Byte.valueOf("0"));
        	}else {
        		user.setSecFlag(us.getFlag());
        	}
        }
        return user;
    }

    @Transactional(readOnly = true)
    @Override
    public boolean existUsername(String username) throws BdexGatewayException {
        User user = new User();
        if (WebConstants.validEmail(username)) {
            user.setEmail(username);
        }
        if (WebConstants.validPhoneNumber(username)) {
            user.setPhone(username);
        }
        List<User> list = selectBySelective(user);
        if (list != null && list.size() > 0) {
            return true;
        }
        return false;
    }

    @Transactional(readOnly = true)
    @Override
    public String checkRefereeCode(String refereeCode) {
        return userMapper.selectByRefereeCode(refereeCode);
    }

    @Override
    public void sendVerificationCodeToEmail(String receiveEmail, String code) throws BdexGatewayException {

        // 获取系统属性
        Properties properties = System.getProperties();

        // 设置邮件服务器
        properties.setProperty("mail.smtp.host", emailConfig.getHost());
        properties.setProperty("mail.smtp.port", emailConfig.getPort());
        properties.put("mail.smtp.auth", "true");
        try {
            MailSSLSocketFactory sf = new MailSSLSocketFactory();
            sf.setTrustAllHosts(true);
            properties.put("mail.smtp.ssl.enable", "true");
            properties.put("mail.smtp.ssl.socketFactory", sf);
            // 获取默认session对象
            Session session = Session.getInstance(properties, new Authenticator() {
                public PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(emailConfig.getFrom(), emailConfig.getPwd()); // 发件人邮件用户名、密码
                }
            });

            // 创建默认的 MimeMessage 对象
            MimeMessage message = new MimeMessage(session);
            // Set From: 头部头字段
            message.setFrom(new InternetAddress(emailConfig.getFrom()));
            // Set To: 头部头字段
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(receiveEmail));

            // Set Subject: 头部头字段
            message.setSubject("bdex邮箱验证码: ");

            // 设置消息体
            message.setText(code);

            // 发送消息
            Transport.send(message);
        } catch (Exception mex) {
            throw new BdexGatewayException("邮箱发送失败!");
        }
    }

    @Override
    public Long sendVerificationCodeToTelphone(String content, String JUSTSend, String telphone, String dstime,
                                               String msgid, String ext, String msgfmt) throws BdexGatewayException {

        // 判断验证码超时
        if (StringUtils.isEmpty(redisUtil.get(telphone + ":" + JUSTSend))) {
            String result = "";
            OutputStreamWriter out = null;
            BufferedReader in = null;
            StringBuilder params = new StringBuilder();
            String userName = telConfig.getUserName();
            String password = telConfig.getPassword();
            String URL = telConfig.getURL();
            params.append("username=").append(userName).append("&password=").append(pwd(password)).append("&mobile=")
                    .append(telphone).append("&content=").append(content).append("&dstime=").append(dstime)
                    .append("&ext=").append(ext).append("&msgid=").append(msgid).append("&msgfmt=").append(msgfmt);
            try {
                URL realUrl = new URL(URL + "smsSend.do");
                URLConnection conn = realUrl.openConnection();
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setDoOutput(true);
                conn.setDoInput(true);
                out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
                out.write(params.toString());
                out.flush();

                in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
                String line = "";
                while ((line = in.readLine()) != null) {
                    result += line + "\n";
                }
            } catch (Exception e) {
                throw new BdexGatewayException("发送过程中服务异常!");
            }
            Long status = Long.valueOf(result.split("\n")[0]);
            if (status <= 0) // 发送失败
            {
                throw new BdexGatewayException("短信发送失败!");
            }
            redisUtil.set(telphone + ":" + "verification", telphone, 120);
            return Long.valueOf(result.split("\n")[0]);
        } else {
            throw new BdexGatewayException("2分钟内验证码仍然有效!");
        }

    }
    
    @Transactional(readOnly = true)
    @Override
    public List<User> allRelieveLock() throws WarningException {
        List<User> userList = userMapper.allRelieveLock();
        if (userList == null || userList.size() == 0) {
            throw new WarningException("没有查询到您要的数据");
        }
        return userList;
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateRelieveLock(String userId) throws BdexGatewayException {
        int result = userMapper.updateRelieveLock(userId);
        if (result <= 0) {
            throw new BdexGatewayException("修复用户锁定状态失败!");
        }
    }

    private String pwd(String password) {
        return MD5Util.MD5Encode(telConfig.getUserName() + MD5Util.MD5Encode(password));
    }
    
    @Transactional(readOnly = true)
	@Override
	public Set<String> queryUserIdByLevel(int level) throws BdexGatewayException {
		return userMapper.queryUserIdByLevel(level);
	}
    @Transactional(readOnly = true)
	@Override
	public Set<String> queryUserIdByTexLevel(int level) throws BdexGatewayException {
		return userMapper.queryUserIdByTexLevel(level);
	}




}
